﻿using LogLib;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using KAImage;
using KAImage.Config;
using KAImage.Algorithms;
using IPCPhotoEditor.Common;

namespace IPCPhotoEditor
{
    public partial class FormHueSat : Form
    {
        private bool _inited = false;

        private ImageHSLOffset _option = null;
        public ImageHSLOffset Option
        {
            get { return _option; }
        }

        private Bitmap _sourceImage = null;

        private Bitmap _destImage = null;

        private ImageHSLOffset _settings = new ImageHSLOffset();
        private ImageHSLOffset Settings
        {
            get { return _settings; }
        }

        public ChannelHSLOffset TheOption
        {
            get
            {
                return _settings.SelectedOption;
            }
        }

        private QueueTaskManager _taskManager = new QueueTaskManager();

        public WorkImageUpdatedEventHandler WorkImageUpdated = null;
        protected void OnWorkImageUpdated(Bitmap image)
        {
            if (WorkImageUpdated != null)
            {
                WorkImageUpdated(this, new WorkImageUpdatedEventArgs(image));
            }
        }

        public int HueOffset
        {
            get 
            { 
                return TheOption.Hue; 
            }
            set // value∈[-180, 180]
            {
                if(value < -180 || value > 180)
                {
                    throw new Exception("对PercentHue进行无效的赋值: " + value.ToString());
                }
                if (TheOption.Hue == value)
                {
                    return;
                }
                TheOption.Hue = value;
                if (trackBarH != null && trackBarH.Value != value)
                {
                    trackBarH.Value = value;
                }
                if (textBoxPerHue != null)
                {
                    textBoxPerHue.Text = value.ToString();
                }
                if (_inited)
                {
                    OnAdjusting();
                }                
            }
        }

        public int LightnessOffset
        {
            get { return TheOption.Lightness; }
            set     // value∈[-100, 100]
            {
                if (value < -100 || value > 100)
                {
                    throw new Exception("对PercentBrightness进行无效的赋值: " + value.ToString());
                }
                if (TheOption.Lightness == value)
                {
                    return;
                }
                TheOption.Lightness = value;
                if (trackBarB != null && trackBarB.Value != value)
                {
                    trackBarB.Value = value;
                }
                if (textBoxPerB != null)
                {
                    textBoxPerB.Text = value.ToString();
                }
                if (_inited)
                {
                    OnAdjusting();
                }      
            }
        }
      
        public int SaturationOffset
        {
            get { return TheOption.Saturation; }
            set // value∈[-100, 100]
            {
                if (value < -100 || value > 100)
                {
                    throw new Exception("对PercentSaturation进行无效的赋值: " + value.ToString());
                }
                if (TheOption.Saturation == value)
                {
                    return;
                }
                TheOption.Saturation = value;
                if (trackBarS != null && trackBarS.Value != value)
                {
                    trackBarS.Value = value;
                }
                if (textBoxPerS != null)
                {
                    textBoxPerS.Text = value.ToString();
                }
                if (_inited)
                {
                    OnAdjusting();
                }      
            }
        }

        public FormHueSat()
        {
            _option = KAConfigs.HSLOffset;
            InitializeComponent();
        }

        public FormHueSat(Bitmap bmp)
        {
            _sourceImage = bmp.Clone() as Bitmap;
            InitializeComponent();
        }

        private void DisposeImage()
        {
            if (_sourceImage != null)
            {
                _sourceImage.Dispose();
                _sourceImage = null;
            }
            if (_destImage != null)
            {
                _destImage.Dispose();
                _destImage = null;
            }
        }

        private void OnAdjusting()
        {
            if (_sourceImage != null)
            {
                _taskManager.AddTask(new HSLAdjust(this));
            }
        }

        private void buttonCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.Close();
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            if (_option != null)
            {
                _option = _settings;
                _option.Save();
            }
            
            this.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.Close();
        }

        private void InitArray()
        {
            int[] copyData = { 0, 0, 0, 3, 4, 7, 12, 3, 0, 4, 9, 45, 34, 23 };
            Array.Sort(copyData);

            // 去掉首尾重复的最小值和最大值
            int max = copyData.Last();
            int min = copyData.First();
            int begin = Array.LastIndexOf(copyData, min);
            int end = Array.IndexOf(copyData, max);
            int n = end - begin + 1;

            int[] realData = copyData.Skip(begin).Take(n).ToArray();
            MessageBox.Show(realData.ToString());
        }

        internal string GetFormatNumStr(int val)
        {
            if(val > 0)
            {
                return "+" + val.ToString();
            }           
            else
            {
                return val.ToString();
            }
        }

        private void InitCtrls()
        {
            _inited = false;
            trackBarB.Value = (int)TheOption.Lightness;
            trackBarH.Value = (int)TheOption.Hue;
            trackBarS.Value = (int)TheOption.Saturation;

            textBoxPerB.Text = TheOption.Lightness.ToString();
            textBoxPerHue.Text = TheOption.Hue.ToString();
            textBoxPerS.Text = TheOption.Saturation.ToString();
            _inited = true;
        }

        private void trackBarH_Scroll(object sender, EventArgs e)
        {
            HueOffset = trackBarH.Value;       
        }

        private void trackBarS_Scroll(object sender, EventArgs e)
        {
           SaturationOffset = trackBarS.Value;
        }

        private void trackBarB_Scroll(object sender, EventArgs e)
        {
            LightnessOffset = trackBarB.Value;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBoxChannels.SelectedIndex = 0;
            _taskManager.Context = SynchronizationContext.Current;           
            _taskManager.StartWorking();
            if (_option != null)
            {
                _settings = _option;
                _settings.SelectedIndex = 0;
                InitCtrls();
            }
            buttonLoad.Visible = (_sourceImage != null);
        }

        private void buttonSaveConfig_Click(object sender, EventArgs e)
        {
            _settings.Save();
        }

        private void textBoxPerHue_TextChanged(object sender, EventArgs e)
        {
            string stemp = textBoxPerHue.Text;
            if (string.IsNullOrEmpty(stemp) || stemp.Equals("-") || stemp.Equals("."))
            {
                return;
            }
            try
            {
                HueOffset = int.Parse(textBoxPerHue.Text);         
            }
            catch (Exception)
            {

            }               
        }

        private void textBoxPerS_TextChanged(object sender, EventArgs e)
        {
            string stemp = textBoxPerS.Text;
            if (string.IsNullOrEmpty(stemp) || stemp.Equals("-") || stemp.Equals("."))
            {
                return;
            }
            try
            {
                SaturationOffset = Convert.ToInt32(textBoxPerS.Text);
            }
            catch (Exception)
            {
               
            }            
        }

        private void textBoxPerHue_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            int val;
            if (int.TryParse(textBoxPerHue.Text, out val))
            {
                if (val < -180 || val > 180)
                {
                    string infoErr = string.Format("请输入一个[{0},{1}]范围内的数字.", -180, 180);
                    errorProvider1.SetError(textBoxPerHue, infoErr);
                }
                else
                {
                    //Value = val;
                    errorProvider1.SetError(textBoxPerHue, "");
                }
            }
            else
            {
                errorProvider1.SetError(textBoxPerHue, "不是合法的数字!");
                textBoxPerHue.Focus();
            }
        }

        private void textBoxPerS_Validating(object sender, System.ComponentModel.CancelEventArgs e)
        {
            TextBox tb = sender as TextBox;
            int val;
            if (int.TryParse(tb.Text, out val))
            {
                if (val < -100 || val > 100)
                {
                    string infoErr = string.Format("请输入一个[{0},{1}]范围内的数字.", -100, 100);
                    errorProvider1.SetError(tb, infoErr);
                }
                else
                {
                    //Value = val;
                    errorProvider1.SetError(tb, "");
                }
            }
            else
            {
                errorProvider1.SetError(tb, "不是合法的数字!");
                tb.Focus();
            }
        }

        private void textBoxPerB_TextChanged(object sender, EventArgs e)
        {
            string stemp = textBoxPerB.Text;
            if (string.IsNullOrEmpty(stemp) || stemp.Equals("-") || stemp.Equals("."))
            {
                return;
            }
            try
            {
                LightnessOffset = Convert.ToInt32(textBoxPerB.Text);
            }
            catch (Exception)
            {

            }              
        }

        private void textBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\b'
                 || Char.IsDigit(e.KeyChar)
                 || Char.IsControl(e.KeyChar)
                 || e.KeyChar == 45
                 || e.KeyChar == 46)
            {
                e.Handled = false;
            }
            else
            {
                e.Handled = true;
            }
        }

        private void FormHueSat_FormClosing(object sender, FormClosingEventArgs e)
        {
            WorkImageUpdated = null;
            _taskManager.Stop(2000);
            DisposeImage();
        }

        private void comboBoxChannels_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = comboBoxChannels.SelectedIndex;
            if (index >= 0)
            {
                _settings.SelectedIndex = index;
            }
            InitCtrls();
        }

        private void OnWorkingInMainThread(Action handler)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(handler, new object[] { });
            }
        }


        private void buttonApply_Click(object sender, EventArgs e)
        {

        }

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            ImageHSLOffset option = new ImageHSLOffset();
            option.Load();
            _settings = option;
            _settings.SelectedIndex = comboBoxChannels.SelectedIndex;
            InitCtrls();
            OnAdjusting();
        }


        public class HSLAdjust : IQueueAction
        {
            private FormHueSat parent = null;

            public HSLAdjust(FormHueSat form)
            {
                parent = form;
                Timestamp = DateTime.Now.Ticks;
                Timeout = 3000;
                _settings = parent.Settings;
            }

            public long Timestamp
            {
                set;
                get;
            }

            public int Timeout
            {
                set;
                get;
            }

            private Bitmap _sourceImage = null;

            private Bitmap _destImage = null;

            private ImageHSLOffset _settings = null;

            public ChannelHSLOffset TheOption
            {
                get
                {
                    if (_settings != null)
                    {
                        return _settings.SelectedOption;
                    }
                    return null;
                }
            }

            public void OnPrepared()
            {
                int index = parent.comboBoxChannels.SelectedIndex;
                PrimaryChannel channel = (PrimaryChannel)(index - 1);          
                _sourceImage = parent._sourceImage;
                _destImage = parent._destImage;
            }

            public void Execute()
            {
                if (_destImage != null)
                {
                    _destImage.Dispose();
                    _destImage = null;
                }
                _destImage = _sourceImage.Clone() as Bitmap;
                if (!_settings.IsDefault)
                {
                    _destImage.SetHSLOffset(_settings);
                }
            }

            public void Simulate()
            {

            }

            public void UpdateUI()
            {              
                parent.OnWorkImageUpdated(_destImage.Clone() as Bitmap);
                //MessageBox.Show(timeCount.ToString());
            }
        }

    }
}
